package apply.apply3;

import apply.data.Person;
import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 反射的应用3：调用指定的结构：指定的属性、方法、构造器
 */
public class ApplyTest {
    /**
     * 调用指定的属性
     */
    //     public int age = 1;
    @Test
    public void test1() throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
        Class<Person> clazz = Person.class;
        Constructor<Person> constructor = clazz.getConstructor();
        Person person = constructor.newInstance();
        // 1.获取运行时类指定名的属性
        Field age = clazz.getField("age");

        // 2.获取或设置此属性的值
        age.set(person, 2);
        System.out.println(age.get(person));

        System.out.println(person);
    }

    //     private String name;
    @Test
    public void test2() throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException, NoSuchFieldException {
        Class<Person> clazz = Person.class;
        Constructor<Person> constructor = clazz.getConstructor();
        Person person = constructor.newInstance();

        // 1.获取运行时类指定名的属性
        Field name = clazz.getDeclaredField("name");
        name.setAccessible(true);

        // 2.获取或设置此属性的值
        name.set(person, "Tom");
        System.out.println(person);
    }

    //    private static String info;
    @Test
    public void test3() throws NoSuchFieldException, IllegalAccessException {
        Class<Person> clazz = Person.class;
        Field info = clazz.getDeclaredField("info");
        info.setAccessible(true); // 确保此属性是可访问的
        info.set(Person.class, "Tom--Cat");
        String string = (String) info.get(Person.class);
        System.out.println(string);
    }

    /**
     * 调用指定的方法
     */
    // private String showNation(String nation, int age);
    @Test
    public void testMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        Class<Person> personClass = Person.class;
        Method showNation = personClass.getDeclaredMethod("showNation", String.class, int.class);
        showNation.setAccessible(true);

        Constructor<Person> constructor = personClass.getConstructor();
        Person person = constructor.newInstance();

        System.out.println(showNation.invoke(person, "China", 25));
    }

    /**
     * 调用指定的构造器
     */
//    private Person(String name, int age);
    @Test
    public void testConstructor() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<Person> clazz = Person.class;
        Constructor<Person> constructor = clazz.getDeclaredConstructor(String.class, int.class);
        constructor.setAccessible(true);
        Person person = constructor.newInstance("Jerry", 11);
        System.out.println(person);
    }
}
